﻿using System;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
using GiveAQuiz.Data;
using GiveAQuiz.Web.Authentication;
using GiveAQuiz.Web.Helpers;
using GiveAQuiz.Web.Messenger;
using Moq;
using NUnit.Framework;

namespace GiveAQuizSite.Tests.Controllers
{
  public abstract class AuthenticationControllerTest
  {
    protected Mock<IPrincipal> MockPrincipal
    {
      get;
      set;
    }

    protected Mock<IIdentity> MockIdentity
    {
      get;
      set;
    }

    protected Mock<MembershipUser> MockUser
    {
      get;
      set;
    }

    protected Mock<HttpContextBase> MockHttpContext
    {
      get;
      set;
    }

    protected Mock<HttpSessionStateBase> MockHttpSession
    {
      get;
      set;
    }

    protected Mock<IWebPathHelper> MockWebHelper
    {
      get;
      set;
    }

    protected Mock<IQuizRepository> MockRepository
    {
      get; set;
    }

    protected Mock<IFormsAuthentication> MockFormsAuthentication
    {
      get;
      set;
    }

    protected Mock<IAccountMessenger> MockAccountMessenger
    {
      get;
      set;
    }

    [TestFixtureSetUp]
    public void InitializeMocks()
    {
      MockIdentity = new Mock<IIdentity>();
      MockIdentity.SetupGet(i => i.AuthenticationType).Returns("MockAuthentication");
      MockIdentity.SetupGet(i => i.IsAuthenticated).Returns(true);
      MockIdentity.SetupGet(i => i.Name).Returns("someUser");

      MockPrincipal = new Mock<IPrincipal>();
      MockPrincipal.SetupGet(p => p.Identity).Returns(MockIdentity.Object);
      MockPrincipal.Setup(p => p.IsInRole(It.IsAny<string>())).Returns(false);

      MockUser = CreateMockUser();

      MockHttpSession = new Mock<HttpSessionStateBase>();

      MockHttpContext = new Mock<HttpContextBase>();
      MockHttpContext.SetupGet(ctx => ctx.User).Returns(MockPrincipal.Object);
      MockHttpContext.Setup(ctx => ctx.Session).Returns(MockHttpSession.Object);

      MockRepository = new Mock<IQuizRepository>();
      MockAccountMessenger = new Mock<IAccountMessenger>();
      MockFormsAuthentication = new Mock<IFormsAuthentication>();
    }

    public static Mock<MembershipUser> CreateMockUser()
    {
      var mockUser = new Mock<MembershipUser>();
      mockUser
        .Setup(u => u.ChangePassword(It.IsAny<string>(), It.IsAny<string>()))
        .Returns<string, string>((oldPass, newPass) => newPass.Equals("newPass"));
      mockUser.SetupGet(m => m.UserName).Returns("user");
      mockUser.SetupGet(m => m.ProviderUserKey).Returns(Guid.NewGuid());
      return mockUser;
    }

    public class MockMembershipProvider : MembershipProvider
    {
      string _applicationName;

      public override string ApplicationName
      {
        get
        {
          return _applicationName;
        }
        set
        {
          _applicationName = value;
        }
      }

      public override bool EnablePasswordReset
      {
        get
        {
          return false;
        }
      }

      public override bool EnablePasswordRetrieval
      {
        get
        {
          return false;
        }
      }

      public override int MaxInvalidPasswordAttempts
      {
        get
        {
          return 0;
        }
      }

      public override int MinRequiredNonAlphanumericCharacters
      {
        get
        {
          return 0;
        }
      }

      public override int MinRequiredPasswordLength
      {
        get
        {
          return 6;
        }
      }

      public override string Name
      {
        get
        {
          return null;
        }
      }

      public override int PasswordAttemptWindow
      {
        get
        {
          return 3;
        }
      }

      public override MembershipPasswordFormat PasswordFormat
      {
        get
        {
          return MembershipPasswordFormat.Clear;
        }
      }

      public override string PasswordStrengthRegularExpression
      {
        get
        {
          return null;
        }
      }

      public override bool RequiresQuestionAndAnswer
      {
        get
        {
          return false;
        }
      }

      public override bool RequiresUniqueEmail
      {
        get
        {
          return false;
        }
      }

      public override bool ChangePassword(string username, string oldPassword, string newPassword)
      {
        throw new NotImplementedException();
      }

      public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
      {
        throw new NotImplementedException();
      }

      public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, Object providerUserKey, out MembershipCreateStatus status)
      {
        var user = CreateMockUser().Object;

        if (username.Equals("someUser") && password.Equals("goodPass") && email.Equals("email"))
        {
          status = MembershipCreateStatus.Success;
        }
        else
        {
          // the 'email' parameter contains the status we want to return to the user
          status = (MembershipCreateStatus)Enum.Parse(typeof(MembershipCreateStatus), email);
        }

        return user;
      }

      public override bool DeleteUser(string username, bool deleteAllRelatedData)
      {
        throw new NotImplementedException();
      }

      public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
      {
        throw new NotImplementedException();
      }

      public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
      {
        throw new NotImplementedException();
      }

      public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
      {
        throw new NotImplementedException();
      }

      public override int GetNumberOfUsersOnline()
      {
        throw new NotImplementedException();
      }

      public override string GetPassword(string username, string answer)
      {
        throw new NotImplementedException();
      }

      public override string GetUserNameByEmail(string email)
      {
        throw new NotImplementedException();
      }

      public override MembershipUser GetUser(Object providerUserKey, bool userIsOnline)
      {
        throw new NotImplementedException();
      }

      public override MembershipUser GetUser(string username, bool userIsOnline)
      {
        return CreateMockUser().Object;
      }

      public override string ResetPassword(string username, string answer)
      {
        throw new NotImplementedException();
      }

      public override bool UnlockUser(string userName)
      {
        throw new NotImplementedException();
      }

      public override void UpdateUser(MembershipUser user)
      {
        throw new NotImplementedException();
      }

      public override bool ValidateUser(string username, string password)
      {
        return password.Equals("goodPass");
      }

    }
  }
}
